<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>变量提升和函数提升</h1>

<script>

    //1.通常以下四种情况会出现undefined.
    /*
    let num;
    let person=new Object();
    //第一种情况：输出未初始化的变量num
    console.log(num);
    //第二种情况：获取未定义的变量a的类型
    console.log(typeof(a));

    function fn(){

    }
    //第三种情况：获取没有返回值的函数的结果
    console.log(fn());
    //第四种情况：获取对象未定义的属性。
    console.log(person.age);
    */

    //2.什么是Hosting（提升）
     /*
    console.log(a);
    var a = "a";
    var foo = () => {
        console.log(a);
        var a = "a1";
    }
    foo();
    */
    //等同于以下代码。
    /*
    var a;
    console.log(a); //undefined
    var a = "a";
    var foo = () => {
        var a; //全局变量会被局部作用域中的同名变量覆盖
        console.log(a); //undefined
        var a = "a1";
    }
    foo();
     */


    //ES6新增了let和const关键字，使得js也有了“块”级作用域，而且使用let和const 声明的变量和函数是不存在提升现象的，
    // 比较有利于我们养成良好的编程习惯。
    console.log(a);
    let a = "a";
    var foo = () => {
        console.log(a);
        let a = "a1";
    }
    foo();

    //3.函数提升
    /*
    console.log(foo1); // [Function: foo1]
    foo1(); // foo1
    console.log(foo2); // undefined
    foo2(); // TypeError: foo2 is not a function
    function foo1 () {
        console.log("foo1");
    };
    var foo2 = function () {
        console.log("foo2");
    };

    */


    //等同于以下代码。
    //函数声明被提升到顶端
    function foo1 () {
        console.log("foo1");
    };
    console.log(foo1); // [Function: foo1]
    foo1(); // foo1

    var foo2;
    console.log(foo2); // undefined
    foo2(); // TypeError: foo2 is not a function

    var foo2 = function () {
        console.log("foo2");
    };

</script>
</body>
</html>